iT邦幫忙

2022 iThome 鐵人賽

DAY 22
0

現在我們來用二分搜尋來解這題,數學推導太長了而且網上還蠻多的就先跳過…

我們用紙牌遊戲代替一下,這個規則就是

1.只能把排放到比目前牌面比較小的那疊

(圖)

2.如果每一疊都比牌面小,則右邊新建一疊,然後把這張牌放到新的一疊去

(圖)

3.如果同時有多疊都可以放置,則放置到最左邊的那疊

(圖)

4.在結束後,從最右邊開始,往回排列出最長遞增子序列

(圖)

然後我們將處理撲克牌的過程,用程式設計出來即可,每次處理一張撲克牌,要先尋找一個合適的牌堆來放,而最後牌堆頂的牌有序,如此便能使用二分搜尋,透過二分搜尋找尋目前要處理的撲克牌應該擺放的位置.

有了這些概念我們來實做看看

fun lengthOfLISBinary(nums: Array<Int>):Int{
    val top =  IntArray(nums.size)
    var piles = 0//牌堆初始為0
    for(i in nums.indices){
        val poker = nums[i] //待處理的牌
        
        var left = 0
        var right = piles
        while(left<right){
            val mid = left + (right - left) / 2
            when {
                top[mid]>poker -> {
                    right = mid
                }
                top[mid]<poker -> {
                    left = mid+1
                }
                else -> {
                    right = mid
                }
            }
        }
        
        //沒有找到可以放置的牌堆,新建立一個
        if(left == piles){
            piles++
        }
        top[left] = poker
    }
    return piles //排堆的總數就是LIS的總數
}

這個做法很難去想到,首先第一步要先進行數學證明,才能利用紙牌遊戲的規則,推導出獲得LIS的值.然後有了規則,又要想到使用二分搜尋法進行優化.而在寫二分搜尋法時,又要很注重細節.才能夠寫得正確.

所以,一般來說還是使用昨天的動態規劃版本就好,利用數學歸納法簡單好懂些.


上一篇
Day 21: 最長遞增子序列
下一篇
Day 23 :俄羅斯套娃信封問題
系列文
從零開始的LeetCode生活,使用Kotlin學習刷題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言